/****************************************************************************************
 * 
 *  Author:         CFY
 *  Date:           2025-07-08
 *  Description:    MQTT通信处理
 *  Version:        V1.1
 * 
****************************************************************************************/

#include "mqtt_handler.h"
#include "yyz_handler.h"

#define QOS         1                                   // MQTT 模式(0,1,2)
#define TIMEOUT     10000L                              // 操作超时时间

// MQTT客户端
static MQTTClient client;
static MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;     // 连接选项
static MQTTClient_deliveryToken token;                                                  // 消息令牌

// 确保变量在多线程环境中正确访问， 记录最后一个确认发送的消息令牌
volatile MQTTClient_deliveryToken deliveredtoken;

int msg_queue_id;

// 消息发送确认回调
void delivered(void *context, MQTTClient_deliveryToken dt)
{
    //printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

// 消息接收回调函数， 当订阅的主题有新消息时触发， 负责解析和处理收到的消息
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    char buf[1024];
    struct Msg msg;
    msg.msg_type = MSG_QUEUE_TYPE;

    char data[1024];
    memset(data, 0, sizeof(data));
    memcpy(data, message->payload, message->payloadlen);
    buf[strlen(data)] = '\0';
    
    // 处理接收到的指令
    // ....
    cmd_handle(data, buf);

    // 打印接收到的指令
    printf("----------recv success!\n");
    printf("%s\n", data);
    printf("%s\n", buf);
    // 向消息队列发送消息
    strcpy(msg.buf, buf);
    if(0 != msg_queue_send(msg_queue_id, (void*)&msg, sizeof(buf), 0))
    {
        printf("add msg queue error!\n");
        return -1;
    }
    printf("add msg queue success!\n");


    MQTTClient_freeMessage(&message);       // 释放消息内存
    MQTTClient_free(topicName);             // 释放主题内存
    return 1;
}

// 连接丢失回调
void connlost(void *context, char *cause)
{
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}


/**
 * @brief           初始化MQTT
 * @param addr      MQTT 服务器 IP地址
 * @return          0   成功， -1  失败              
 */
int mqtt_init(const char *addr)
{

    if(NULL == addr)
    {
        printf("addr can not be empty!\n");
        return -1;
    }
    
    // 连接MQTT服务器的地址
    char mqtt_addr[256];
    sprintf(mqtt_addr, "tcp://%s:%d", addr, MQTT_PORT);

    // 创建 MQTT 客户端实例
    MQTTClient_create(&client, mqtt_addr, MQTT_CLIENTID,MQTTCLIENT_PERSISTENCE_NONE, NULL);

    // 配置连接选项
    conn_opts.keepAliveInterval = 20;       // 心跳间隔（秒）
    conn_opts.cleansession = 1;             // 清楚会话标志（1表示每次连接都是新会话）

    // 设置回调函数
    MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);

    int rc; 
    // 连接到MQTT代理服务器
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        ERROR("MQTTClient_connect");
        printf("Failed to connect, return code %d\n", rc);
        return -1;
    }

    
    // 订阅消息主题
    MQTTClient_subscribe(client, TOPIC_CTL_DOWN, QOS);
    //MQTTClient_subscribe(client, TOPIC_DATA_DOWN, QOS);

    printf("[Success] : Connected to MQTT Broker at %s\n", mqtt_addr);


    return 0;
}

/**
 * @brief           向一个主题发送消息
 * @param topic     主题
 * @param msg       要发送的消息
 * @return          成功    返回 0
 *                  失败    返回 -1           
 */
int mqtt_publish(const char *topic, char *msg)
{
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    pubmsg.payload = msg;
    pubmsg.payloadlen = (int)strlen(msg);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;    

    // 发送消息
    MQTTClient_publishMessage(client, topic, &pubmsg, &token);
    // 等待消息发送完成
    int rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
    // 检查发送结果
    if (rc != MQTTCLIENT_SUCCESS) 
    {
        printf("Failed to deliver message, return code %d\n\n", rc);
        return -1;
    } 
 
    printf("----------send success [token = %d]\n", token);
    printf("[%s] : [%s]\n\n", topic, msg);

    return 0;
}
